#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015  Data Enlighten Technology (Beijing) Co.,Ltd


import time
import Lib.Logger.log4py as log

import base64
import os
import re
from time import clock

from mj_parser import common_errors
# from mj_parser.utils import get_brand_group

from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait  # available since 2.4.0


class AudiWebParser:
    default_result = {
        'model': '',
        'year': '',
        'manufacture_date': '',
        'type': '',
        'engine': '',
        'transmission': '',
        'body': '',
        'setting': '',
        'inner_color': '',
        'color': '',
        'manufacturer': '',
        'production_code': '',
        'engine_number': '',
        'country_symbol': '',
        'content': '',
        'brand': '',
        'pr_list': '',
        'raw_content': ''
    }

    def __init__(self, root_dir):
        self.root_dir = root_dir
        self.account_path = os.path.join(root_dir, "conf", "login.txt")
        self.cookie_path = os.path.join(root_dir, "conf", "audi_cookie.txt")
        self.driver_path = os.path.join(root_dir, "bin", "chromedriver.exe")
        self.data_path = os.path.join(root_dir, "data")
        self.counter_path = os.path.join(root_dir, "data", "Count.TMP")
        self.credential = self.load_credentials()

        # 初始化 Count.TMP
        with open(self.counter_path, 'a') as fi:
            os.utime(self.counter_path)

        self.driver = webdriver.Chrome(self.driver_path)

        # 必须初始化执行，否则无法产生instance用于load cookie
        self.driver.get("https://www.partslink24.com/partslink24/user/login.do")

        try:
            self.driver.get("https://www.partslink24.com.cn/partslink24/user/login.do")
            cookie_dict = self.load_cookie()
            for cookie in cookie_dict:
                self.driver.add_cookie(cookie)
            time.sleep(1)

        except Exception as ex:
            log.e(ex)

    def ready(self):
        return True

    def get_data(self, str_vin, brand, group):
        b = ''
        try:
            t0 = clock()
            print(t0)
            time_format = '%Y-%m-%d %X'
            log.d(time.strftime(time_format, time.localtime()))

            b, dict_merge = self.get_config_data(str_vin, brand, group)

            fobj = open(self.counter_path, mode='r', encoding='utf_8_sig')
            con = fobj.read()
            if not con:
                n = 1
            else:
                n = int(con.replace('\n', ''))
            fobj.close()
            fobj = open(self.counter_path, mode='w+', encoding='utf_8_sig')
            if n > 20:
                self.logout()
                fobj.writelines('0')
            else:
                fobj.writelines(str(n + 1))

            fobj.close()
            t2 = clock()
            print(t2 - t0)
            if b == common_errors.ERR_SUCCESS:
                if dict_merge is None or len(dict_merge) == 0:
                    dict_default = {'body': '', 'series': '', 'mod_year': '', 'year': '', 'pr': ''}
                    return b, dict_default
                else:
                    return b, dict_merge

        except Exception as ex:
            log.e(ex)
        return b, None

    def logon_input(self):
        input_element = self.driver.find_element_by_name("accountLogin")
        input_element.clear()
        input_element.send_keys(self.credential[0])
        input_element = self.driver.find_element_by_name("userLogin")
        input_element.clear()
        input_element.send_keys(self.credential[1])
        input_element = self.driver.find_element_by_name("loginBean.password")
        input_element.send_keys(self.credential[2])

        self.driver.find_element_by_id("login-btn").click()
        try:
            WebDriverWait(self.driver, 3).until(lambda driver: driver.find_element_by_id('logout'))
        except NoSuchElementException as ex:
            log.e(ex)
        except TimeoutException as te:
            log.e(te)

    def logout(self):
        self.driver.get('https://www.partslink24.com.cn/vwag/logout.action')

    def wait_for_element(self, wbdriver, tpye, value, timeout):
        try:
            if tpye == 'id':
                WebDriverWait(wbdriver, timeout).until(lambda driver: driver.find_element_by_id('value'))
            if type == 'title':
                WebDriverWait(wbdriver, timeout).until(lambda driver: driver.current_url.find(value) >= 0)
        except NoSuchElementException as ex:
            log.e(ex)
        except TimeoutException as te:
            log.e(te)

    def try_login(self, brand, group):
        url_login = 'https://www.partslink24.com.cn/partslink24/user/login.do'

        url_prefix = 'https://www.partslink24.com.cn/{0}/{1}_parts/vehicle.action?mode=A0LW0CNCN'.format(group, brand)
        url = url_prefix + '&lang=zh&startup=true'

        for count in range(0, 10):
            try:

                self.driver.get(url)
                if self.driver.page_source.find("Error 404") >= 0 or self.driver.current_url.find(url_prefix) < 0:
                    time.sleep(120)
                    self.driver.get(url_login)
                    self.logon_input()
                elif self.driver.page_source.find("您已注销退出partslink24。请再次登录以继续使用partslink24。") >= 0:
                    print('find 您已注销退出partslink24。')
                    self.logon_input()
                    continue
                else:
                    return True
            except Exception as ex:
                log.e(ex)
                time.sleep(120)
                return False
        return False

    def get_config_data(self, str_vin, brand, group):
        check_flag = self.try_login(brand, group)
        if not check_flag:
            return '82', self.get_default_result()

        try:
            self.save_cookie()
            input_element = self.driver.find_element_by_name("vin")
            input_element.send_keys(str_vin)
            input_element.submit()
            time.sleep(1)

            vin_file = os.path.join(self.data_path, "{0}.html".format(str_vin))
            fp = open(vin_file, 'w', encoding='utf-8')
            fp.write(self.driver.page_source)
            fp.close()

            if brand == 'bmw' or brand == 'mini':
                b, result_list = self.parser_html_bmw(vin_file)
            else:
                b, result_list = self.parser_html_vw(vin_file)
            if b != common_errors.ERR_SUCCESS:
                return b, result_list
            if result_list is not None and len(result_list) > 0:
                return common_errors.ERR_SUCCESS, result_list

        except Exception as ex:
            log.e(ex)
            time.sleep(120)
        return '99', self.get_default_result()

    def find_string(self, html, name):
        p = re.compile('<th>' + name + '</th><td colspan="2">.+?</tr>', re.S)
        html_div_chn_li = p.findall(html)
        if html_div_chn_li is not None and len(html_div_chn_li) > 0:
            return html_div_chn_li[0].replace('<th>' + name + '</th><td colspan="2">', '').replace('</tr>', '').replace(
                '</td>', '').replace('\t', '').replace('\n', '').replace('&nbsp;', '').replace('\xa0', '')
        else:
            return ''

    def find_template_value(self, html, name):
        p = re.compile('"' + name + '":.+?,', re.S)
        html_div_chn_li = p.findall(html)
        if html_div_chn_li is not None and len(html_div_chn_li) > 0:
            return html_div_chn_li[0].replace('"' + name + '":', '').replace(',', '')
        else:
            return ''

    def parser_html_bmw(self, file_name):
        result_list = self.get_default_result()
        b = common_errors.ERR_SUCCESS
        try:
            fobj = open(file_name, encoding='utf_8_sig')
            html = fobj.read()
            b = common_errors.ERR_SUCCESS

            if html.find('没有找到您搜索的车辆识别代码的数据。该车辆识别代码不存在或者尚未输入相关车辆数据') >= 0:
                b = common_errors.ERR_NO_VIN
                return b, result_list
            result_list['mospid'] = self.find_template_value(html, 'mospid')
            result_list['upds'] = self.find_template_value(html, 'upds')

            p = re.compile('<h2>标准设备</h2></td></tr></thead><tbody>.+?</tbody>', re.S)
            html_div_chn_li = p.findall(html)

            sa_list = []
            li = []
            if html_div_chn_li is not None and len(html_div_chn_li) > 0:

                p = re.compile('<tr><td>.+?</td>', re.S)
                model_li = p.findall(html_div_chn_li[0])
                for x in model_li:
                    x = x.replace('<tr><td>', '').replace('</td>', '').replace('\t', '').replace('\n', '')
                    li.append(x)
                sa_list += li
            p = re.compile('<h2>专用附件</h2></td></tr></thead><tbody>.+?</tbody>', re.S)
            html_div_chn_li = p.findall(html)

            if html_div_chn_li is not None and len(html_div_chn_li) > 0:
                li = []
                p = re.compile('<tr><td>.+?</td>', re.S)
                model_li = p.findall(html_div_chn_li[0])
                for x in model_li:
                    x = x.replace('<tr><td>', '').replace('</td>', '').replace('\t', '').replace('\n', '')
                    li.append(x)
                sa_list += li
            if len(li) > 0:
                result_list['pr_list'] = '|'.join(sa_list)
            else:
                result_list['pr_list'] = ''

        except Exception as ex:
            print(ex)
        return b, result_list

    def parser_html_vw(self, file_name):
        b = common_errors.ERR_SUCCESS
        result_list = self.get_default_result()
        try:
            fobj = open(file_name, encoding='utf_8_sig')
            html = fobj.read()

            if html.find('没有找到您搜索的车辆识别代码的数据。该车辆识别代码不存在或者尚未输入相关车辆数据') >= 0:
                b = common_errors.ERR_NO_VIN
                return b, result_list

            # 车型特殊处理
            tempstr = self.find_string(html, '机型')
            model_format_string = self.find_string(html, '车型') if len(tempstr) == 0 else tempstr

            p = re.compile('<span style="font-weight: normal;">.+? </span>', re.S)
            model_li = p.findall(model_format_string)
            if model_li is not None and len(model_li) > 0:
                result_list['model'] = model_li[0].replace('<span style="font-weight: normal;">', '').replace('</span>',
                                                                                                              '')
            else:
                result_list['model'] = ''

            result_list['year'] = self.find_string(html, '车型年份')
            result_list['manufacture_date'] = self.find_string(html, '生产日期')
            result_list['type'] = self.find_string(html, '销售类型')
            result_list['engine'] = self.find_string(html, '发动机代码')
            result_list['transmission'] = self.find_string(html, '变速器代码')
            result_list['body'] = self.find_string(html, '前后桥标识')
            result_list['setting'] = self.find_string(html, '配置')
            result_list['inner_color'] = self.find_string(html, '顶部颜色')
            result_list['color'] = self.find_string(html, '外观颜色 / 油漆号')

            result_list['manufacturer'] = ''
            result_list['production_code'] = ''
            result_list['engine_number'] = ''
            result_list['country_symbol'] = ''
            result_list['content'] = self.find_template_value(html, 'episType')
            result_list['brand'] = ''
            result_list['raw_content'] = base64.b64encode(html.encode('utf-8')).decode('utf-8')
            p = re.compile('<td class="prCode">.+?</td>', re.S)
            html_div_chn_li = p.findall(html)

            if html_div_chn_li is not None and len(html_div_chn_li) > 0:
                li = []
                for x in html_div_chn_li:
                    x = x.replace('<td class="prCode">', '').replace('</td>', '').replace('\t', '').replace('\n', '')
                    li.append(x)
                result_list['pr_list'] = '|'.join(li)
            else:
                result_list['pr_list'] = ''

        except Exception as ex:
            print(ex)
        return b, result_list

    def load_cookie(self):
        result_list = []
        file_object = open(self.cookie_path, 'r')
        p = file_object.read()
        response_list = p.split(';')
        for res in response_list:
            result_list.append(eval(res))

        file_object.close()
        return result_list

    def save_cookie(self):
        cookie = "; ".join([str(item) for item in self.driver.get_cookies()])
        file_object = open(self.cookie_path, 'w')
        file_object.write(cookie)
        file_object.close()

    def get_default_result(self):
        return AudiWebParser.default_result.copy()

    def load_credentials(self):
        if not os.path.exists(self.account_path):
            raise Exception("No credential present: missing {0}".format(self.account_path))

        with open(self.account_path, 'r') as fi:
            content = fi.read()
            credential = content.split('\n')
            if credential is None or len(credential) != 3:
                raise Exception("Error loading credential")
            return credential


# if __name__ == "__main__":

    # info = get_brand_group('LSFSR33N493431341')
    # if info[1] == '':
    #     print('brand wsa null')
    #
    # parser = AudiWebParser()
    # parser.get_config_data('LSFSR33N493431341', 'vw', 'vw')

